package utils

import (
	"errors"
	"fmt"
	"github.com/APP/global"
	"gorm.io/gorm"
)

// MPTTNode MPTT节点接口
type MPTTNode interface {
	GetID() int64
	GetParentID() *int64
	GetLeft() int
	GetRight() int
	GetLevel() int
	SetLeft(left int)
	SetRight(right int)
	SetLevel(level int)
	TableName() string
}

// MPTTManager MPTT管理器
type MPTTManager struct {
	db *gorm.DB
}

// NewMPTTManager 创建MPTT管理器
func NewMPTTManager() *MPTTManager {
	return &MPTTManager{
		db: global.APP_DB,
	}
}

// InsertNode 插入节点
func (m *MPTTManager) InsertNode(node MPTTNode, parentID *int64) error {
	return m.db.Transaction(func(tx *gorm.DB) error {
		if parentID == nil {
			// 插入根节点
			return m.insertRootNode(tx, node)
		} else {
			// 插入子节点
			return m.insertChildNode(tx, node, *parentID)
		}
	})
}

// insertRootNode 插入根节点
func (m *MPTTManager) insertRootNode(tx *gorm.DB, node MPTTNode) error {
	// 获取最大右值
	var maxRight int
	err := tx.Table(node.TableName()).Select("COALESCE(MAX(`right`), 0)").Scan(&maxRight).Error
	if err != nil {
		return fmt.Errorf("获取最大右值失败: %v", err)
	}

	// 设置节点的左右值和层级
	node.SetLeft(maxRight + 1)
	node.SetRight(maxRight + 2)
	node.SetLevel(1)

	// 插入节点
	return tx.Table(node.TableName()).Create(node).Error
}

// insertChildNode 插入子节点
func (m *MPTTManager) insertChildNode(tx *gorm.DB, node MPTTNode, parentID int64) error {
	// 查找父节点
	var parent map[string]interface{}
	err := tx.Table(node.TableName()).Where("id = ?", parentID).First(&parent).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("父节点不存在")
		}
		return fmt.Errorf("查找父节点失败: %v", err)
	}

	parentRight := int(parent["right"].(int64))
	parentLevel := int(parent["level"].(int64))

	// 更新所有右值大于等于父节点右值的节点
	err = tx.Table(node.TableName()).Where("`right` >= ?", parentRight).
		Update("`right`", gorm.Expr("`right` + 2")).Error
	if err != nil {
		return fmt.Errorf("更新右值失败: %v", err)
	}

	// 更新所有左值大于父节点右值的节点
	err = tx.Table(node.TableName()).Where("`left` > ?", parentRight).
		Update("`left`", gorm.Expr("`left` + 2")).Error
	if err != nil {
		return fmt.Errorf("更新左值失败: %v", err)
	}

	// 设置新节点的左右值和层级
	node.SetLeft(parentRight)
	node.SetRight(parentRight + 1)
	node.SetLevel(parentLevel + 1)

	// 插入节点
	return tx.Table(node.TableName()).Create(node).Error
}

// DeleteNode 删除节点及其所有子节点
func (m *MPTTManager) DeleteNode(node MPTTNode) error {
	return m.db.Transaction(func(tx *gorm.DB) error {
		// 获取节点信息
		var nodeData map[string]interface{}
		err := tx.Table(node.TableName()).Where("id = ?", node.GetID()).First(&nodeData).Error
		if err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return errors.New("节点不存在")
			}
			return fmt.Errorf("查找节点失败: %v", err)
		}

		left := int(nodeData["left"].(int64))
		right := int(nodeData["right"].(int64))
		width := right - left + 1

		// 删除节点及其所有子节点
		err = tx.Table(node.TableName()).Where("`left` >= ? AND `right` <= ?", left, right).Delete(node).Error
		if err != nil {
			return fmt.Errorf("删除节点失败: %v", err)
		}

		// 更新所有右值大于被删除节点右值的节点
		err = tx.Table(node.TableName()).Where("`right` > ?", right).
			Update("`right`", gorm.Expr("`right` - ?", width)).Error
		if err != nil {
			return fmt.Errorf("更新右值失败: %v", err)
		}

		// 更新所有左值大于被删除节点右值的节点
		err = tx.Table(node.TableName()).Where("`left` > ?", right).
			Update("`left`", gorm.Expr("`left` - ?", width)).Error
		if err != nil {
			return fmt.Errorf("更新左值失败: %v", err)
		}

		return nil
	})
}

// MoveNode 移动节点到新的父节点下
func (m *MPTTManager) MoveNode(nodeID int64, newParentID *int64, tableName string) error {
	return m.db.Transaction(func(tx *gorm.DB) error {
		// 获取要移动的节点信息
		var nodeData map[string]interface{}
		err := tx.Table(tableName).Where("id = ?", nodeID).First(&nodeData).Error
		if err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return errors.New("节点不存在")
			}
			return fmt.Errorf("查找节点失败: %v", err)
		}

		left := int(nodeData["left"].(int64))
		right := int(nodeData["right"].(int64))
		level := int(nodeData["level"].(int64))
		width := right - left + 1

		// 检查是否移动到自己的子节点下
		if newParentID != nil {
			var count int64
			err = tx.Table(tableName).Where("id = ? AND `left` > ? AND `right` < ?", *newParentID, left, right).Count(&count).Error
			if err != nil {
				return fmt.Errorf("检查父节点失败: %v", err)
			}
			if count > 0 {
				return errors.New("不能移动到自己的子节点下")
			}
		}

		var newLeft, newLevel int

		if newParentID == nil {
			// 移动到根级别
			var maxRight int
			err = tx.Table(tableName).Select("COALESCE(MAX(`right`), 0)").Scan(&maxRight).Error
			if err != nil {
				return fmt.Errorf("获取最大右值失败: %v", err)
			}
			newLeft = maxRight + 1
			newLevel = 1
		} else {
			// 移动到指定父节点下
			var parentData map[string]interface{}
			err = tx.Table(tableName).Where("id = ?", *newParentID).First(&parentData).Error
			if err != nil {
				if errors.Is(err, gorm.ErrRecordNotFound) {
					return errors.New("新父节点不存在")
				}
				return fmt.Errorf("查找新父节点失败: %v", err)
			}
			newLeft = int(parentData["right"].(int64))
			newLevel = int(parentData["level"].(int64)) + 1
		}

		levelDiff := newLevel - level
		offset := newLeft - left

		// 如果新位置在原位置之后，需要调整偏移量
		if newLeft > left {
			offset -= width
		}

		// 临时标记要移动的节点（使用负值）
		err = tx.Table(tableName).Where("`left` >= ? AND `right` <= ?", left, right).
			Updates(map[string]interface{}{
				"`left`":  gorm.Expr("0 - `left`"),
				"`right`": gorm.Expr("0 - `right`"),
			}).Error
		if err != nil {
			return fmt.Errorf("临时标记节点失败: %v", err)
		}

		// 为新位置腾出空间
		if newLeft <= left {
			// 新位置在原位置之前
			err = tx.Table(tableName).Where("`left` >= ?", newLeft).
				Update("`left`", gorm.Expr("`left` + ?", width)).Error
			if err != nil {
				return fmt.Errorf("更新左值失败: %v", err)
			}

			err = tx.Table(tableName).Where("`right` >= ?", newLeft).
				Update("`right`", gorm.Expr("`right` + ?", width)).Error
			if err != nil {
				return fmt.Errorf("更新右值失败: %v", err)
			}
		} else {
			// 新位置在原位置之后
			err = tx.Table(tableName).Where("`left` > ?", right).
				Update("`left`", gorm.Expr("`left` - ?", width)).Error
			if err != nil {
				return fmt.Errorf("更新左值失败: %v", err)
			}

			err = tx.Table(tableName).Where("`right` > ?", right).
				Update("`right`", gorm.Expr("`right` - ?", width)).Error
			if err != nil {
				return fmt.Errorf("更新右值失败: %v", err)
			}
		}

		// 移动节点到新位置
		err = tx.Table(tableName).Where("`left` < 0").
			Updates(map[string]interface{}{
				"`left`":  gorm.Expr("0 - `left` + ?", offset),
				"`right`": gorm.Expr("0 - `right` + ?", offset),
				"`level`": gorm.Expr("`level` + ?", levelDiff),
			}).Error
		if err != nil {
			return fmt.Errorf("移动节点失败: %v", err)
		}

		return nil
	})
}

// GetChildren 获取节点的所有子节点
func (m *MPTTManager) GetChildren(nodeID int64, tableName string, result interface{}) error {
	var nodeData map[string]interface{}
	err := m.db.Table(tableName).Where("id = ?", nodeID).First(&nodeData).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("节点不存在")
		}
		return fmt.Errorf("查找节点失败: %v", err)
	}

	left := int(nodeData["left"].(int64))
	right := int(nodeData["right"].(int64))

	return m.db.Table(tableName).Where("`left` > ? AND `right` < ?", left, right).
		Order("`left` ASC").Find(result).Error
}

// GetAncestors 获取节点的所有祖先节点
func (m *MPTTManager) GetAncestors(nodeID int64, tableName string, result interface{}) error {
	var nodeData map[string]interface{}
	err := m.db.Table(tableName).Where("id = ?", nodeID).First(&nodeData).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("节点不存在")
		}
		return fmt.Errorf("查找节点失败: %v", err)
	}

	left := int(nodeData["left"].(int64))
	right := int(nodeData["right"].(int64))

	return m.db.Table(tableName).Where("`left` < ? AND `right` > ?", left, right).
		Order("`left` ASC").Find(result).Error
}

// GetTree 获取完整的树形结构
func (m *MPTTManager) GetTree(tableName string, result interface{}) error {
	return m.db.Table(tableName).Order("`left` ASC").Find(result).Error
}

// RebuildTree 重建树的左右值（修复数据不一致的情况）
func (m *MPTTManager) RebuildTree(tableName string) error {
	return m.db.Transaction(func(tx *gorm.DB) error {
		// 获取所有根节点
		var roots []map[string]interface{}
		err := tx.Table(tableName).Where("parent_id IS NULL").Order("id ASC").Find(&roots).Error
		if err != nil {
			return fmt.Errorf("获取根节点失败: %v", err)
		}

		counter := 1
		for _, root := range roots {
			counter = m.rebuildNode(tx, tableName, int64(root["id"].(int64)), counter, 1)
		}

		return nil
	})
}

// rebuildNode 递归重建节点的左右值
func (m *MPTTManager) rebuildNode(tx *gorm.DB, tableName string, nodeID int64, left int, level int) int {
	right := left + 1

	// 获取所有子节点
	var children []map[string]interface{}
	tx.Table(tableName).Where("parent_id = ?", nodeID).Order("id ASC").Find(&children)

	// 递归处理子节点
	for _, child := range children {
		right = m.rebuildNode(tx, tableName, int64(child["id"].(int64)), right, level+1)
	}

	// 更新当前节点的左右值和层级
	tx.Table(tableName).Where("id = ?", nodeID).Updates(map[string]interface{}{
		"`left`":  left,
		"`right`": right,
		"`level`": level,
	})

	return right + 1
}

// ValidateTree 验证树的完整性
func (m *MPTTManager) ValidateTree(tableName string) error {
	// 检查左右值的完整性
	var count int64
	err := m.db.Table(tableName).Where("`left` >= `right`").Count(&count).Error
	if err != nil {
		return fmt.Errorf("检查左右值失败: %v", err)
	}
	if count > 0 {
		return fmt.Errorf("发现 %d 个左值大于等于右值的节点", count)
	}

	// 检查是否有重复的左值或右值
	err = m.db.Raw(fmt.Sprintf("SELECT COUNT(*) FROM (SELECT `left` FROM %s GROUP BY `left` HAVING COUNT(*) > 1) AS duplicates", tableName)).Scan(&count).Error
	if err != nil {
		return fmt.Errorf("检查重复左值失败: %v", err)
	}
	if count > 0 {
		return errors.New("发现重复的左值")
	}

	err = m.db.Raw(fmt.Sprintf("SELECT COUNT(*) FROM (SELECT `right` FROM %s GROUP BY `right` HAVING COUNT(*) > 1) AS duplicates", tableName)).Scan(&count).Error
	if err != nil {
		return fmt.Errorf("检查重复右值失败: %v", err)
	}
	if count > 0 {
		return errors.New("发现重复的右值")
	}

	return nil
}
